package com.lry;

import lombok.extern.slf4j.Slf4j;

/**
 * 资源管理器
 */
@Slf4j
public class Rm {

    private String name;
    private Tc tc;
    public boolean error;

    public Rm(String name,Tc tc){
        this.name = name;
        this.tc = tc;
    }

    //一阶段
    public void business(String xid) {
        log.info("rm={},business,注册分支事务，xid={}",name,xid);

        tc.branchRegister(xid,this);

        //生成前后置镜像，undo log
        String beforeImg = "before img";
        String businessSql = "update before img to after img";
        log.info("rm={},do self business sql={},xid={}",name,businessSql,xid);//业务数据库操作
        String afterImg = "after img";

        String undoLog = "beforeImg="+beforeImg+",afterImg="+afterImg;
        String undoLogSql = "insert into undo_log set rollback_info="+undoLog;
        log.info("rm={},do undo log sql={},xid={}",name,undoLogSql,xid);//undo log数据库操作

        try{
            localCommit();//本地提交sql
        }catch (Exception e){
            report(xid,false);
            throw e;
        }
        report(xid,true);
    }

    //一阶段如果失败可以直接终止事务
    private void report(String xid,boolean commitResult) {
        tc.report(xid,commitResult);
    }

    private void localCommit() {
        log.info("rm={}提交业务sql和undo log sql",name);
        if(error){
            throw new RuntimeException("rm="+name+"内部错误");
        }
    }


    //二阶段
    public void rollback(String xid) {

        log.info("RM={}收到tc的回滚消息PhaseTwo_Rollbacked，开始删除undo log, 并反向补偿，xid={}",name,xid);

        String beforeImg = "before img";
        String afterImg = "after img";
        String undoLog = "beforeImg="+beforeImg+",afterImg="+afterImg;

        String reverseBusinessSql = "update after img to before img";

        log.info("通过undo log={}生成逆向sql={}",undoLog,reverseBusinessSql);
        log.info("删除undo log,并反向补偿");
    }

    //二阶段
    public void commit(String xid) {
        log.info("RM={}收到tc的提交消息PhaseTwo_Committed，开始删除undo log，xid={}",name,xid);

        String beforeImg = "before img";
        String afterImg = "after img";
        String undoLog = "beforeImg="+beforeImg+",afterImg="+afterImg;

        log.info("删除undo log={}",undoLog);
    }
}
